Next | Prev | Up | Top | Contents | Index

Basic Locks

IRIX supports basic locks using functions compatible with SVR4. These functions are summarized in Table 9-16.

Functions for Basic Locks
Function NameHeader FilesCan Sleep?Purpose
LOCK(D3) ksynch.h & types.hYAcquire a basic lock, waiting if necessary.
LOCK_ALLOC(D3) ksynch.h,kmem.h & types.hYAllocate and initialize a basic lock.
LOCK_DEALLOC(D3) ksynch.h & types.hNDeallocate an instance of a basic lock.
LOCK_INIT(D3)ksynch.h & types.hNInitialize a basic lock that was allocated statically, or reinitialize an allocated lock.
LOCK_DESTROY(D3)ksynch.h & types.hNUninitialize a basic lock that was allocated statically.
TRYLOCK(D3) types.h & ksynch.hNTry to acquire a basic lock, returning a code if the lock is not currently free.
UNLOCK(D3) types.h & ksynch.hNRelease a basic lock.

Basic locks are objects of type lock_t. Although functions are provided for allocating and freeing them, a basic lock is a very small object. Locks are typically allocated as global variables or as fields of structures.

Call LOCK() to seize a lock and gain possession of the resource for which it stands. Release the lock with UNLOCK(). These functions are optimized for mutual exclusion in the available hardware, and may be implemented differently in uniprocessors and multiprocessors. However, the programming and binary interface is the same in all systems.

The code in Example 9-1 illustrates the use of LOCK and UNLOCK in implementing a simple last-in-first-out (LIFO) queueing package. In these functions, the time between locking a queue head and releasing it is only a few microseconds.

Example 9-1 : LIFO Queue Using Basic Locks

typedef struct qitem {
   qitem *next; ...other fields...
} qitem_t;
typedef struct lifo {
   qitem *latest;
   lock_t grab;
} lifo_t;
void putlifo(lifo_t *q, qitem_t *i)
{
   int lockpl = LOCK(&q->grab,plhi);
   i->next = q->latest;
   q->latest = i;
   UNLOCK(&q->grab,lockpl);
}
qitem_t *poplifo(lifo_t *q)
{
   int lockpl = LOCK(&q->grab,plhi);
   qitem_t *ret = q->latest;
   q->latest = ret->next;
   UNLOCK(&q->grab,lockpl);
   return ret;
}
This is a typical use of basic locks: to ensure that for a brief period only one process in the system can update a queue. Basic locks are optimized for such uses, but in order to get optimal performance they are restricted to these uses. In particular, if you seize a basic lock and hold it over a function call that can sleep, the system can deadlock.


Next | Prev | Up | Top | Contents | Index